#include "can_drv.h"
#include <string.h>
// Can控制器的初始化状态:成功或失败
static int MyCanInitStatusflag = ERROR;

/**
 * @desc  : 引脚配置
 * @date  : 2025-07-30
 * @author: AnRui
 * @note  :
 */
static void GpioConfig(void) {
    rcu_periph_clock_enable(CAN_TX_RCU);
    gpio_init(CAN_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN_TX_PIN);
    rcu_periph_clock_enable(CAN_RX_RCU);
    gpio_init(CAN_RX_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN_RX_PIN);
}

/**
 * @desc  : CAN控制器配置
 * @date  : 2025-07-30
 * @author: AnRui
 * @note  :
 */
static void CanConfig(void) {
    rcu_periph_clock_enable(CAN_X_RCU);
    can_parameter_struct        canInitPara;                  // CAN初始化参数
    can_struct_para_init(CAN_INIT_STRUCT, &canInitPara);      // CAN参数设为默认值
    /* 初始化CAN0寄存器 */
    can_deinit(CAN_X);
    canInitPara.time_triggered = DISABLE;             // 禁用时间触发通信
    canInitPara.auto_bus_off_recovery = ENABLE;       // 允许 CAN 控制器在进入总线关闭状态后，可以自动恢复
    canInitPara.auto_wake_up = DISABLE;               // 自动唤醒功能: 当设备进入到睡眠模式后, 允许设备在监测到总线上的活动时，自动从睡眠模式切换到正常工作模式，无需软件干预
    canInitPara.auto_retrans = ENABLE;                // 启用自动重传，确保报文发送成功（发送失败会一直重新发送）
    canInitPara.rec_fifo_overwrite = DISABLE;         //接收 FIFO 满时      DISABLE:新来的数据直接丢弃   ENABLE: 最后进来的数据被新来的数据覆盖
    canInitPara.trans_fifo_order = DISABLE;           // 按ID顺序发送（ID小的优先）
    canInitPara.working_mode = CAN_SILENT_LOOPBACK_MODE;// 正常通信模式:CAN_NORMAL_MODE  CAN_SILENT_LOOPBACK_MODE：静默回环模式
    canInitPara.resync_jump_width = CAN_BT_SJW_1TQ;   // 再同步补偿宽度
    canInitPara.time_segment_1 = CAN_BT_BS1_7TQ;      // 位段1
    canInitPara.time_segment_2 = CAN_BT_BS2_2TQ;      // 位段2
    canInitPara.prescaler = 6;                        // 分频系数，APB1时钟60Mhz，波特率：60 / (6 * (1 + 7 + 2)) = 1Mbps
    MyCanInitStatusflag = can_init(CAN_X, &canInitPara);
    if (MyCanInitStatusflag == ERROR) {
        printf("MyCanInit error \r\n");
    }
    // 中断相关
//    can_interrupt_enable(CAN0, CAN_INT_RFNE0);     // 使能FIFO0非空中断CAN0_RX1_IRQn
//    nvic_irq_enable(USBD_LP_CAN0_RX0_IRQn, 0, 0);  // 使能CAN中断
}

/**
 * @desc  : CAN过滤器配置
 * @date  : 2025-07-29
 * @author: AnRui
 * @note  :
 */
static void CanFilterConfig(void) {
    can_filter_parameter_struct canFilterPara;                // CAN过滤器初始化参数
    can_struct_para_init(CAN_FILTER_STRUCT, &canFilterPara);  // 过滤器参数设为默认值
    canFilterPara.filter_number = 0;                                            // 过滤器单元编号 0~13
    canFilterPara.filter_mode = FILTER0_MODE;                            // CAN_FILTERMODE_MASK: 屏蔽模式    CAN_FILTERMODE_LIST:列表模式
    canFilterPara.filter_bits = FILTER0_BITS;                           // CAN_FILTERBITS_16BIT:16位过滤器  CAN_FILTERBITS_32BIT :32位过滤器
    canFilterPara.filter_list_high = FILTER0_LIST_HIGH;                                         // 掩码高位
    canFilterPara.filter_list_low = FILTER0_LIST_LOW;                                          // 掩码低位
    canFilterPara.filter_mask_high = FILTER0_MASK_HIGH;                                         // 掩码高位
    canFilterPara.filter_mask_low = FILTER0_MASK_LOW;                                          // 掩码低位
    canFilterPara.filter_fifo_number = CAN_FIFO0;                               // 关联FIFO
    canFilterPara.filter_enable = ENABLE;                                       // 过滤器激活
    can_filter_init(&canFilterPara);
}


/**
 * @desc  : 发送消息
 * @date  : 2025-07-30
 * @author: AnRui
 * @param : TxMessage - {参数说明}:
 * @note  :
 */
void MyCANTransmit(can_trasnmit_message_struct* TxMessage) {
    if (MyCanInitStatusflag == ERROR) return;
    // 返回放送消息的邮箱号
    uint8_t TransmitMailbox = can_message_transmit(CAN_X, TxMessage);
    uint32_t Timeout = 0;
    while (can_transmit_states(CAN_X, TransmitMailbox) != CAN_TRANSMIT_OK) {
        Timeout++;
        if (Timeout > 100000) {
            break;
        }
    }
}



/**
 * @desc  : CAN中断控制器配置
 * @date  : 2025-07-31
 * @author: AnRui
 * @note  :
 *    中断类型:
 *      CAN_INT_TME: 发送邮箱空中断使能。当发送邮箱数据发送完成变为空时触发，用于通知软件可向该邮箱填充新数据
 *      CAN_INT_RFNE0: 接收FIFO0非空中断使能。当FIFO0中有至少一帧数据时触发，用于通知软件读取新接收的数据
 *      CAN_INT_RFF0: 接收FIFO0满中断使能。当FIFO0存储的数据达到最大容量（通常3帧）时触发，警告即将溢出
 *      CAN_INT_RFO0: 接收FIFO0溢出中断使能。当FIFO0已满且新帧到来时触发，提示新数据被丢弃（数据丢失）
 *      CAN_INT_RFNE1: 接收FIFO1非空中断使能。功能同RFNE0，对应接收FIFO1
 *      CAN_INT_RFF1: 接收FIFO1满中断使能。功能同RFF0，对应接收FIFO1
 *      CAN_INT_RFO1: 接收FIFO1溢出中断使能。功能同RFO0，对应接收FIFO1
 *      CAN_INT_WERR: 警告错误中断使能。当错误计数超过96时触发，提示总线存在干扰（即将进入错误状态）
 *      CAN_INT_PERR: 被动错误中断使能。当错误计数超过127时触发，控制器进入被动状态（发送受限，仅能接收）
 *      CAN_INT_BO: 总线关闭中断使能。当错误计数超过255时触发，控制器完全无法收发，需软件恢复
 *      CAN_INT_ERRN: 错误数量中断使能。当错误计数发生变化时触发，用于实时监控错误计数
 *      CAN_INT_ERR: 错误中断总使能。使能后所有错误相关中断（WERR/PERR等）均会触发
 *      CAN_INT_WAKEUP: 唤醒中断使能。当控制器从睡眠模式被总线活动唤醒时触发
 *      CAN_INT_SLPW: 睡眠-工作模式切换中断使能。当控制器在睡眠与工作模式间切换时触发
 */
void MyCANInteruptConfig() {
    can_interrupt_enable(CAN_X, CAN_INT_RFNE0);
    nvic_irq_enable(USBD_LP_CAN0_RX0_IRQn, 0, 0);
}
void USBD_LP_CAN0_RX0_IRQHandler(void) {
    if (can_interrupt_flag_get(CAN_X, CAN_INT_FLAG_RFL0) == SET) {
        printf("can trigger\r\n");
        can_interrupt_flag_clear(CAN_X, CAN_INT_FLAG_RFL0);
    }
}


/**
 * @desc  : 检测是否接收到消息
 * @date  : 2025-07-30
 * @author: AnRui
 * @return: uint8_t
 * @note  :
 */
uint8_t MyCANReceiveFlag(void) {
    if (MyCanInitStatusflag == ERROR) return 0;
    if (can_receive_message_length_get(CAN_X, CAN_FIFO0) > 0) {
        return 1;
    }
    return 0;
}

/**
 * @desc  : 接受消息
 * @date  : 2025-07-30
 * @author: AnRui
 * @param : RxMessage - {参数说明}:
 * @note  :
 */
void MyCAN_Receive(can_receive_message_struct* RxMessage) {
    if (MyCanInitStatusflag == ERROR) return;
    can_message_receive(CAN_X, CAN_FIFO0, RxMessage);
}

/**
 * @desc  : CAN控制器测试
 * @date  : 2025-07-30
 * @author: AnRui
 * @note  :
 */
void CANDrvTest(void) {
    printf("CANDrvTest \r\n");
    uint8_t dataBuf[1] = { 1 };
    can_trasnmit_message_struct TxMessag;
    TxMessag.tx_sfid = 0x00;            // 标准ID
    TxMessag.tx_efid = 0x12329978u;   // 扩展ID
    TxMessag.tx_ft = CAN_FT_DATA;     // 数据帧: CAN_FT_DATA  遥控帧:CAN_FT_REMOTE
    TxMessag.tx_ff = CAN_FF_EXTENDED; // 标准格式: CAN_FF_STANDARD 扩展格式: CAN_FF_EXTENDED
    TxMessag.tx_dlen = sizeof(dataBuf);
    memcpy(&TxMessag.tx_data, dataBuf, sizeof(dataBuf));
    MyCANTransmit(&TxMessag);
    //    while (!MyCANReceiveFlag());
    //    printf("--- Received CAN Message ---\r\n");
    //    can_receive_message_struct RxMessage;
    //    MyCAN_Receive(&RxMessage);
    //    printf("sfid:%x \r\n ", RxMessage.rx_sfid);
    //    printf("exid:%x \r\n ", RxMessage.rx_efid);
    //    printf("frame type:%s \r\n ", RxMessage.rx_ft == CAN_FT_DATA ? "data" : "remote");
    //    printf("frame formate:%s \r\n ", RxMessage.rx_ff == CAN_FF_STANDARD ? "standard" : "extended");
    //    printf("data len:%d \r\n ", RxMessage.rx_dlen);
    //    for (int i = 0; i < RxMessage.rx_dlen; i++) {
    //        printf("data:0x%02x \r\n ", RxMessage.rx_data[i]);
    //    }
    //    printf("filter index:%02x \r\n ", RxMessage.rx_fi);
    //    printf("----------------------------\r\n");
}
/**
 * @desc  : CAN控制器初始化
 * @date  : 2025-07-30
 * @author: AnRui
 * @note  :
 */
void CANDrvInit() {
    GpioConfig();
    CanConfig();
    CanFilterConfig();
    // MyCANInteruptConfig();
}

